package br.ufmg.dcc.vod.remoteworkers.sync;

import java.rmi.RemoteException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import br.ufmg.dcc.vod.remoteworkers.AbstractTestCase;
import br.ufmg.dcc.vod.remoteworkers.util.MyThread;
import br.ufmg.dcc.vod.remoteworkers.util.PreRaceControlledCommand;
import br.ufmg.dcc.vod.remoteworkers.util.RaceConditionCommand;
import br.ufmg.dcc.vod.remoteworkers.util.SyncQueueBasedLock;

public class ThreadSafeSyncCommandProcessorTest extends AbstractTestCase {

	public void testProcess() throws RemoteException, InterruptedException {
		ExecutorService pool = Executors.newFixedThreadPool(2);
		
		SyncQueueBasedLock processorLock = new SyncQueueBasedLock();
		SyncCommandProcessorWLock processor = new SyncCommandProcessorWLock(new ThreadSafeSyncCommandProcessor(PORT), processorLock);
		
		SyncQueueBasedLock commandLock = new SyncQueueBasedLock();
		RaceConditionCommand c1 = new PreRaceControlledCommand(commandLock);
		assertEquals(-1, c1.getID().intValue());
		
		RaceConditionCommand c2 = new RaceConditionCommand();
		assertEquals(-1, c2.getID().intValue());
		
		MyThread t1 = new MyThread(processor, c1);
		MyThread t2 = new MyThread(processor, c2);

		pool.execute(t1);
		commandLock.unlock(); //wait until c1 executed
		
		pool.execute(t2);
		commandLock.unlock(); //liberate c1. starts race
		
		processorLock.unlock();
		assertEquals(0, c1.getID().intValue());
		
		processorLock.unlock();
		assertEquals(1, c2.getID().intValue());
		
		pool.shutdown();
		pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); //wait until everybody stops
	}
}